﻿using Mrsoft.Properties;
using SevenZip;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Mrsoft.Update.Common;

namespace Mrsoft
{
    public partial class FrmUpdate : Form
    {

        private readonly Config<int> _softConfig;
        private readonly Queue<string> _downlist;
        private readonly WebClient _downloader;
        private readonly string _temPath;

        /// <summary>
        /// 下载程序加载
        /// </summary>
        /// <param name="softConfig"></param>
        /// <param name="downlist"></param>
        public FrmUpdate(Config<int> softConfig, Queue<string> downlist)
        {
            InitializeComponent();
            Icon = Resources._3;
            this._softConfig = softConfig;
            this._downlist = downlist;
            _downloader = new WebClient();
            _downloader.DownloadProgressChanged += Downloader_DownloadProgressChanged;
            _downloader.DownloadFileCompleted += Downloader_DownloadFileCompleted;
            _temPath = Path.Combine(Application.StartupPath, "RollBack");
            if (!Directory.Exists(_temPath))
            {
                Directory.CreateDirectory(_temPath);
            }
            progressBar2.Maximum = downlist.Count;
            var worker = new Task(Work);
            worker.Start();
        }

        private void Downloader_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            if (this.InvokeRequired)
            {
                var del = new DownloadProgressChangedEventHandler(Downloader_DownloadProgressChanged);
                this.Invoke(del, sender, e);
            }
            else
            {
                progressBar1.Value = e.ProgressPercentage;
            }
        }

        private void ProgressBar2Change()
        {
            if (this.InvokeRequired)
            {
                var del = new MethodInvoker(ProgressBar2Change);
                this.Invoke(del);
            }
            else
            {
                progressBar2.Value++;
            }
        }


        private void Downloader_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            var oldList = new Dictionary<string, string>();
            SevenZipExtractor sevenZipExtractor = null;
            try
            {
                sevenZipExtractor = new SevenZipExtractor(e.UserState as string);
                var files = sevenZipExtractor.ArchiveFileNames;
                //拷贝文件表
                foreach (var file in files)
                {
                    var sourcefile = Path.Combine(Application.StartupPath, file);
                    if (File.Exists(sourcefile))
                    {
                        //备份文件名
                        var temfileName = Path.Combine(_temPath, file);
                        //备份文件路径
                        var temfilePath = temfileName.Remove(temfileName.LastIndexOf("\\"));
                        //检查路径
                        if (!Directory.Exists(temfilePath))
                            Directory.CreateDirectory(temfilePath);
                        if (File.Exists(temfileName))
                            File.Delete(temfileName);
                        File.Copy(sourcefile, temfileName);
                        oldList.Add(temfileName, sourcefile);
                    }
                }
                string currentDirectory = Directory.GetCurrentDirectory();
                sevenZipExtractor.ExtractArchive(currentDirectory);
                sevenZipExtractor.Dispose();
                //fs.Close();
                Thread.Sleep(1000);
                ProgressBar2Change();
                _softConfig.Value++;
                Work();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                if (sevenZipExtractor != null)
                {
                    sevenZipExtractor.Dispose();
                    Thread.Sleep(1000);
                }
                //文件还原
                foreach (var file in oldList)
                {
                    if (File.Exists(file.Key))
                        File.Move(file.Key, file.Value);
                }
                MessageBox.Show(ex.Message, "更新失败了");
            }

        }


        /// <summary>
        /// 下载处理线程
        /// </summary>
        private void Work()
        {
            if (_downlist.Count > 0)
            {
                var url = _downlist.Dequeue();
                var path = Path.Combine(_temPath, "tem.zip");
                DownloadFile(url, path);
                Invoke((MethodInvoker)delegate {
                    this.Text = string.Format("下载第{0}版本的文件……", _softConfig.Value);
                });
            }
            else
            {
                Directory.Delete(_temPath, true);
                Invoke((MethodInvoker)delegate {
                    Close();
                });
            }
        }


        private void FrmUpdate_FormClosing(object sender, FormClosingEventArgs e)
        {
            _downloader.Dispose();
        }

        public void DownloadFile(string url, string fileName)
        {
            _downloader.DownloadFileAsync(new Uri(url), fileName, fileName);
        }



    }

}

/*
 * 1.0
 * 更新程序的逻辑部分
 * 1.加载更新目录
 * 2.顺序下载文件包
 * 3.顺序解压缩文件包替换资源
 * 4.渐进提升版本号
 * ------
 * 1.1
 * 对软件资源进行统一的编号并且存留副本　并且对副本文件MD5编码
 * 更新的时候才用优先更新副本再更新文件
 * 对更新软件进行优化 下载和解压缩剥离
 * 下载由主程序直接进行
 * 软件解压替换则有update来执行?
 * 从软件包里抽取文件 执行更新
 */